home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / c / qtools0.2-src.lha / src / libqdisplay / collide.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-19  |  5.2 KB  |  177 lines

  1. #define    LIBQDISPLAY_CORE
  2. #include "../include/libqdisplay.h"
  3.  
  4. /*
  5.  * clipping-hulls
  6.  *
  7.  *  hull[0] drawing-hull
  8.  *  hull[1] player-hull        ((-16,-16,-24),(16,16,32))
  9.  *  hull[2] shambler-hull    ((-32,-32,-24),(32,32,64))
  10.  */
  11.  
  12. static bool point_plane_test(register vec3_t point, register struct dplane_t *plane)
  13. {
  14. #if (PLANE_X == 0) && (PLANE_Y == 1) && (PLANE_Z == 2)
  15.   vec_t val;
  16.  
  17.   if (plane->type < PLANE_Z)
  18.     val = point[plane->type];
  19.   else
  20.     val = DotProduct(plane->normal, point);
  21.  
  22.   return val < plane->dist;
  23. #else
  24.   switch (plane->type) {
  25.     case PLANE_X:
  26.       return point[0] < plane->dist;
  27.       break;
  28.     case PLANE_Y:
  29.       return point[1] < plane->dist;
  30.       break;
  31.     case PLANE_Z:
  32.       return point[2] < plane->dist;
  33.       break;
  34.     default:
  35.       return DotProduct(plane->normal, point) < plane->dist;
  36.       break;
  37.   }
  38. #endif
  39. }
  40.  
  41. short int find_clipcontents(__memBase, register short int n)
  42. {
  43.   struct dclipnode_t *node;
  44.  
  45.   do {
  46.     node = &bspMem->shared.quake1.dclipnodes[n];
  47.   } while ((n = node->children[point_plane_test(&bspMem->shared.quake1.dplanes[node->planenum])]) >= 0);
  48.  
  49.   return n;
  50. }
  51.  
  52. /*
  53.  * we execute as long as bsp_clip_node returns FALSE,
  54.  * that means we get a dead-lock (endless loop) if we cannot
  55.  * break the line any more, so we dont continue in that case
  56.  *
  57.  * the splitting is as follows
  58.  *  we calculate the length between start and end point, if its 0 we break
  59.  *  else we check for intersection, if nothing intersects we break
  60.  *  else we check how long is the way we can go (which MUST be less than
  61.  *  length), we go that length
  62.  *  now we rotate the direction of the leaved move to the plane ones (not
  63.  *  the direction of the planes normal, the direction of the planes plane),
  64.  *  set the new player start and end and recall the splitting
  65.  */
  66.  
  67. vec3_t player_position;
  68. vec3_t player_target;
  69. struct dplane_t *split_plane;
  70.  
  71. void ClipMove(void) {
  72.   if(!VectorCompare(player_target, player_position)) {
  73.     short int node;                        /* how to calculate the node? */
  74.   
  75.     if(!bsp_clip_node(node)) {
  76.       player_position = player_target;
  77.     }
  78.     else {
  79.       vec3_t move_line, new_move;
  80.       vec_t diff, angle;
  81.  
  82.       VectorSubtract(player_target, player_position, move_line);
  83. #if 0
  84.       player_position = Intersect(move_line, split_plane);
  85. #else
  86. /*
  87.  * math
  88.  
  89.  line-equation
  90.  
  91.   alpha * n_x + b_x
  92.   alpha * n_y + b_y
  93.   alpha * n_z + b_z
  94.  
  95.  plane-equation
  96.  
  97.   distance = DotProduct(point, plane_normal) + plane_dist;
  98.            = point_x * plane_normal_x + point_y * plane_normal_y + point_z * plane_normal_z + plane_dist;
  99.  
  100.  point could be solved with the line-equation
  101.  
  102.            = (alpha * n_x + b_x) * plane_normal_x + 
  103.          (alpha * n_y + b_y) * plane_normal_y +
  104.          (alpha * n_z + b_z) * plane_normal_z +
  105.           plane_dist;
  106.  
  107.            = (alpha * n_x * plane_normal_x) + (b_x * plane_normal_x) +
  108.          (alpha * n_y * plane_normal_y) + (b_y * plane_normal_y) +
  109.          (alpha * n_z * plane_normal_z) + (b_z * plane_normal_z) +
  110.           plane_dist;
  111.  
  112.        = alpha * DotProduct(n, plane_normal) + DotProduct(b, plane_normal) + plane_dist;
  113.  
  114.  the intersection point must be on the plane, so distance must be 0
  115.  
  116.                     0 = alpha * DotProduct(n, plane_normal) + DotProduct(b, plane_normal) + plane_dist;
  117.   alpha * DotProduct(n, plane_normal) = (-DotProduct(b, plane_normal) - plane_dist);
  118.                 alpha = (-DotProduct(b, plane_normal) - plane_dist) / DotProduct(n, plane_normal)
  119.  
  120.  */
  121.       /* how much of move_line can we go */
  122.       diff = (-DotProduct(player_position, split_plane->normal) - plane->dist) / DotProduct(move_line, split_plane->normal);
  123.       VectorScale(move_line, diff, new_move);
  124.       VectorAdd(new_move, player_position);
  125. #endif
  126.       VectorSubtract(player_target, player_position, move_line);
  127. #if 0
  128.       player_target = Rotate(moveline, split_plane);
  129. #else
  130.       /* without rotate, dont know how to do with */
  131.       diff = DotProduct(player_target, split_plane->normal) + split_plane->dist;
  132.       VectorMA(player_target, -diff, split_plane->normal, player_target);
  133. #endif
  134.       ClipMove();
  135.     }
  136.   }
  137. }
  138.  
  139. bool bsp_clip_node(__memBase, short int node)
  140. {
  141.   if (node >= 0) {
  142.     /* positivity of start and end points */
  143.     bool pos_start, pos_end;
  144.     struct dplane_t *plane;
  145.     
  146.     plane = &bspMem->shared.quake1.dplanes[node->planenum];
  147.     pos_start = point_plane_test(player_position, plane);
  148.     pos_end = point_plane_test(player_target, plane);
  149.   
  150.     /* we are on our side of the plane, both are positive */
  151.     if (pos_start && pos_end)
  152.       return bsp_clip_node(bspMem, bspMem->shared.quake1.dclipnodes[node].children[0]);
  153.     /*
  154.      * we are on the other side of the plane, both are negative
  155.      * I think that is not possible, cause we cant be IN solid?
  156.      */
  157.     else if (!pos_start && !pos_end)
  158.       return bsp_clip_node(bspMem, bspMem->shared.quake1.dclipnodes[node].children[1]);
  159.     /* we are in the plane, one is positive and one is negative */
  160.     else {
  161.       /*
  162.        * we split the move, do the partial move and return
  163.        * must ever be positive, cause we cant be IN solid?
  164.        */
  165.       split_plane = plane
  166.       return TRUE;
  167.     }
  168.   }
  169.   else {
  170.     /* we are in solid and must clip the movement */
  171.     if (node == CONTENTS_SOLID)
  172.       return TRUE;
  173.     else
  174.       return FALSE;
  175.   }
  176. }
  177.